CGPointとSIMD

CGPointを触り出すと、いつもelementwiseな四則演算が使いたくなる。

演算子オーバーロードはお行儀が悪い気がして、SIMDプロトコルで解決した例をメモ。

 

extension CGPoint: SIMD {

    public typealias MaskStorage = SIMD2<CGFloat.NativeType>.MaskStorage

    public subscript(index: Int) -> CGFloat {

        get {

            index == 0 ? x : y

        }

        set(newValue) {

            x = index == 0 ? newValue : x

            y = index != 0 ? newValue : y

        }

    }

    public var scalarCount: Int {

        2

    }

    public typealias Scalar = CGFloat

}

 

RWHのCH18

モナド変換子を作ってみるやつのMaybeT、写経してみたけどうまく動かなくて四苦八苦した結果のメモ書き

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-}

module MaybeT where

import Control.Monad.Trans
import Control.Monad.State

newtype MaybeT m a = MaybeT {
    runMaybeT :: m (Maybe a)
}

altBindMT :: Monad m => MaybeT m a -> (a -> MaybeT m b) -> MaybeT m b
x `altBindMT` f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f)

instance (Functor f) => Functor (MaybeT f) where
    fmap = undefined

instance (Applicative a) => Applicative (MaybeT a) where
    pure = undefined
    (<*>) = undefined

instance (Monad m) => Monad (MaybeT m) where
    return a = MaybeT $ return (Just a)
    (>>=) = altBindMT
    fail _ = MaybeT $ return Nothing

instance MonadTrans MaybeT where
    lift = lift

instance (MonadIO m) => MonadIO (MaybeT m) where
    liftIO m = lift (liftIO m)

instance (MonadState s m) => MonadState s (MaybeT m) where
    get = lift get
    put k = lift (put k)

要はアプリカティブとファンクタのインスタンスをundefinedでサボってでもやっとけばコンパイルが通るように。
それぞれちゃんと書いてみたのが以下

liftA2MT :: (Applicative a) => MaybeT a (b -> c) -> MaybeT a b -> MaybeT a c
af `liftA2MT` ax = MaybeT $ fmap (<*>) (runMaybeT af) <*> runMaybeT ax

instance (Functor f) => Functor (MaybeT f) where
    fmap f a = MaybeT $ fmap (fmap f) (runMaybeT a)

instance (Applicative a) => Applicative (MaybeT a) where
    pure a = MaybeT $ pure (Just a)
    (<*>) = liftA2MT

UglyStackの方はどう治せば綺麗に動くのかなぁ?

SwiftのFailable Initializerで、初期化するメンバーが多いとき

ぱっと検索できる範囲でinit?のサンプルを眺めていると、
初期化するメンバー変数が少なく、楽な感じなので不自由なさそうだったけれど、
メンバーが増えてくると煩わしさが倍々で増えていく気がして嫌だった。
例えば以下

class Test {
    
    let member0: Int
    let member1: Int
    let member2: Int
    let member3: Int

    init?( arg0: Int?, arg1: Int?, arg2: Int?, arg3: Int? ) {
        guard
            let m0 = arg0,
            let m1 = arg1,
            let m2 = arg2,
            let m3 = arg3
            else { return nil }
        member0 = m0
        member1 = m1
        member2 = m2
        member3 = m3
    }

}

そこで以下の様にしてみたところ、一対一にはなった。
好き嫌いは分かれると思う。

enum OptionalToExceptionError: Error {
    case failure
}

public func fromOptional<T>(_ optionalTypeValue: T? ) throws -> T {
    if let nonOptionalValue = optionalTypeValue {
        return nonOptionalValue
    } else {
        throw OptionalToExceptionError.failure
    }
}

class TestAlt {
    let member0: Int
    let member1: Int
    let member2: Int
    let member3: Int

    init?( arg0: Int?, arg1: Int?, arg2: Int?, arg3: Int? ) {
        do {
            member0 = try fromOptional( arg0 )
            member1 = try fromOptional( arg1 )
            member2 = try fromOptional( arg2 )
            member3 = try fromOptional( arg3 )
        } catch _ {
            return nil
        }
    }
}

書いてはみたものの、標準ライブラリにありそうな気がする。まだ探していない。

hackageのuploadでつまづいたこと

以下のサイトを参考にhackageへデビューしました。
https://www.ishiy.xyz/posts/2017-01-29-haskell-hackage.html

しかし、一回目のuploadでつまづきました。

stack upload .

としたとこころ、usernameとpasswordを聞かれたところで固まってずっと無反応に。

以下の様なプロンプトが発生しているが表示が隠れているようで、

Save hackage credentials to file at /Users/****/.stack/upload/credentials.json [y/n]?

yまたはnキーを押すことで、先に進むことができます。

関連する項目として以下があるようです。

https://github.com/commercialhaskell/stack/blob/master/doc/yaml_configuration.md#save-hackage-creds

また、一回目の時は代替策として、

stack sdist

でパッケージをつくって、これをhackageのuploaderから送信しました。
https://hackage.haskell.org/upload

SwiftでfilterM

すごいH本最大の難所と僕が勝手に思っているfilterM
Swiftで同じ事出来ないかなと模索してみたところ、できちゃったので、ここに記録。

func filterM<T>(_ p: (T)->[Bool],_ array: [T]) -> [[T]] {
    return array.first.map { x in
        let xs = Array( array.suffix(from: 1) )
        let result: [[T]] = p(x).flatMap{ flg -> [[T]] in
            [filterM(p,xs)].flatMap{ ys -> [[T]] in
                flg ? [[x] + (ys.first ?? []) ] : ys }
        }
        return result
    } ?? []
}

print(filterM( { _ in [true,false] }, [1,2,3] ))

// [[1, 2, 3], [2, 3], [3]]

tensorFlow+OSX+GPUのメモ

tensor flowをDownload and Setupに従ってGPU版のインストールをしたところ、test your installationの最初の一行でつまづきました。このtest your installationを動くようにしたときのメモです。
OS X 10.11、
Xcode 7.3、
CUDA toolkitは8.0、
cuDNNは5.1です

まず、testの一行目、

>>> import tensorflow as tf

でクラッシュに遭遇しました。
これはCUDA Driverへのパスの文字列が空なためにクラッシュしているようで、.bash_profileに以下の行を追加したところ、回避できました。

export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$CUDA_HOME/lib"

これにより

>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')

までは動くようになりますが、

>>> sess = tf.Session()

でエラーを吐いてきます。

I tensorflow/stream_executor/dso_loader.cc:105] Couldn't open CUDA library libcuda.1.dylib. LD_LIBRARY_PATH: :/usr/local/cuda/lib


libcuda.1.dylibを探してるようなのですが、見当たりません。そこで、シンボリックリンクを張ります。

sudo ln -s /usr/local/cuda/lib/libcuda.dylib /usr/local/cuda/lib/libcuda.1.dylib

これで、

>>> sess = tf.Session()
>>> print(sess.run(hello))
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print(sess.run(a + b))
42
>>>

まで一応動きました。

SwiftでLet Over Lambda

SwiftのBlocksに関してググってみるたび、変数キャプチャの簡潔な例がぱっとみつからないので、備忘録として。

let letOverLambda: ()->Int = { var i = 0; return { i += 1; return i } }()

letOverLambda() -> 1
letOverLambda() -> 2
letOverLambda() -> 3